import function.GobleVar;
import function.Core;
import function.GobleTool;
import kit.FileIO;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;

public class Main
{
    static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) throws IOException
    {
        String comment;
        while(true)
        {
            GobleTool.cleanner();
            GobleTool.printHelp();
            comment = scanner.next();
            if (comment.equals("exit"))
                break;
            else if(comment.equals("0"))
                func0();
            else if(comment.equals("1"))
                func1();
            else if(comment.equals("1.1"))
                func1_1();
            else if(comment.equals("2"))
                func2();
            else if(comment.equals("3"))
                func3();
            else if(comment.equals("4"))
                func4();
            else if(comment.equals("5"))
                func5();
            else if(comment.equals("6"))
                func6();
            else if(comment.equals("7"))
                func7();
        }
    }

    public static void func0()
    {
        long startTime1 =  System.currentTimeMillis();
        int user_to_itemCount = 14;
        int item_to_userCount = 22;

        //DONE:采用多线程读取映射文件缓存
        //MARK:设置CountDownLatch以监控线程是否执行完毕
        final CountDownLatch countDownLatch = new CountDownLatch(1+user_to_itemCount+item_to_userCount) ;
        //MARK:多线程读取movieList缓存
        new Thread(() -> {
            try {
                FileIO.readMovieList("d:/teamdata/cache/system/movieList.dat");
            } catch (IOException e) { e.printStackTrace(); }
            countDownLatch.countDown();
        }).start();
        //MARK:多线程读取user_to_item缓存
        for (int i=0;i<user_to_itemCount;i++)
        {
            int finalI = i;
            new Thread(() -> {
                try {
                    FileIO.readMappingItem("d:/teamdata/cache/system/user_to_item"+ finalI +".dat",0);
                } catch (IOException e) { e.printStackTrace(); }
                countDownLatch.countDown();
            }).start();
        }
        //MARK:多线程读取item_to_user缓存
        for (int i=0;i<item_to_userCount;i++)
        {
            int finalI = i;
            new Thread(() -> {
                try {
                    FileIO.readMappingItem("d:/teamdata/cache/system/item_to_user"+ finalI +".dat",1);
                } catch (IOException e) { e.printStackTrace(); }
                countDownLatch.countDown();
            }).start();
        }
        try
        {
            countDownLatch.await();
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        long endTime1 =  System.currentTimeMillis();
        GobleTool.printWaitInfo((endTime1-startTime1)/1000.0 + "秒");
    }

    public static void func1() throws IOException
    {
        long startTime1 =  System.currentTimeMillis();
        init1();init2(false);init3(false);
        long endTime1 =  System.currentTimeMillis();
        GobleTool.printWaitInfo((endTime1-startTime1)/1000 + "秒");
    }

    public static void func1_1() throws IOException
    {
        long startTime1 =  System.currentTimeMillis();
        init1();init2(true);init3(true);
        long endTime1 =  System.currentTimeMillis();
        GobleTool.printWaitInfo((endTime1-startTime1)/1000 + "秒");
    }

    public static void func2() throws IOException
    {
        for (Integer movieId: GobleVar.movieList.keySet())
            Core.readSimilarityCache(movieId);
    }

    public static void func3() throws IOException
    {
        String path="d:/teamdata/cache/endingResult.dat";
        FileIO fileIO = new FileIO();
        fileIO.deleteFile(path);
        for (Integer movieId: GobleVar.movieList.keySet())
            Core.similarity(movieId);
    }

    public static void func4()
    {
        GobleVar.isDebug=true;
    }

    public static void func5()
    {
        GobleVar.isDebug=false;
    }
    public static void func6() throws IOException
    {
        //DONE:添加隐藏功能，输入ID进行实时计算
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入视频ID:");
        Integer moviesId = scanner.nextInt();
        GobleTool.printInfo("正在进行推送计算,请稍后...");
        long startTime =  System.currentTimeMillis();
        //MARK:相似度计算的关键方法调用
        ArrayList<String> result = Core.similarity(moviesId);
        if (result != null)
        {
            for (int i=0;i<result.size();i++)
                System.out.println(result.get(i));

            long endTime =  System.currentTimeMillis();
            double usedTime = (endTime-startTime)/1000.0;
            GobleTool.printWaitInfo("本次处理用时:"+usedTime+"秒");
        }
    }
    public static void func7() throws IOException
    {
        //DONE:添加隐藏功能，输入ID进行缓存查询
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入视频ID:");
        Integer moviesId = scanner.nextInt();
        long startTime =  System.currentTimeMillis();
        //MARK:相似度计算（包含是否已存在缓存判断功能）关键方法调用
        ArrayList<String> result = Core.readSimilarityCache(moviesId);

        for (int i=0;i<result.size();i++)
            System.out.println(result.get(i));

        long endTime =  System.currentTimeMillis();
        double usedTime = (endTime-startTime)/1000.0;
        GobleTool.printWaitInfo("本次处理用时:"+usedTime+"秒");
    }

    public static void init1() throws IOException
    {
        GobleVar.moviesFile = FileIO.readFile("d:/teamdata/movies.dat");
        GobleVar.ratingsFile = FileIO.readFile("d:/teamdata/ratings_train.dat");
    }

    public static void init2(boolean createCache) throws IOException
    {
        Core.initMovies(GobleVar.moviesFile,createCache);
        Core.initRatings(GobleVar.ratingsFile);
    }

    public static void init3(boolean createCache) throws IOException
    {
        Core.initMapping(createCache);
    }
}
